#ifndef RP2OBJECT_H
#define RP2OBJECT_H

#include "Rp2Main.h"
#include "Rp2SmartPointer.h"
#include "Rp2Rtti.h"
#include "Rp2NameIdMCR.h"

namespace Rp2
{

class Controller;

class Object
{
// root class of object system
public:
	virtual ~Object();
protected:
	Object();

// Run-time type information system
public:
	static const Rtti TYPE;
	virtual const Rtti& GetType() const;
    bool IsExactly (const Rtti& rkType) const;
    bool IsDerived (const Rtti& rkType) const;
    bool IsExactlyTypeOf (const Object* pkObject) const;
    bool IsDerivedTypeOf (const Object* pkObject) const;

// controller system
public:
    int GetControllerQuantity () const;
    Controller* GetController (int i) const;
    void AttachController (Controller* pkController);
    void DetachController (Controller* pkController);
    void DetachAllControllers ();
    bool UpdateControllers (double dAppTime);
private:
    // controllers
    std::vector<Pointer<Object> > m_kControllers;

// name-id system
public:
    void SetName (const std::string& rkName);
    const std::string& GetName () const;
    unsigned int GetID () const;
    static unsigned int GetNextID ();
    virtual Object* GetObjectByName (const std::string& rkName);
    virtual void GetAllObjectsByName (const std::string& rkName,
       std::vector<Object*>& rkObjects);
    virtual Object* GetObjectByID (unsigned int uiID);
private:
    std::string m_kName;
    unsigned int m_uiID;
    static unsigned int ms_uiNextID;

// smart pointer system
public:
    void IncrementReferences ();
    void DecrementReferences ();
    int GetReferences () const;
private:
	int m_iReferences;


};

// static and dynamic type casting
template <class T> T* StaticCast (Object* pkObj);
template <class T> const T* StaticCast (const Object* pkObj);
template <class T> T* DynamicCast (Object* pkObj);
template <class T> const T* DynamicCast (const Object* pkObj);

typedef Pointer<Object> ObjectPtr;
#include "Rp2Object.inl"

}

#endif